package com.zjj.learn.algorithmPlus.segment1.stack;

import java.util.Arrays;
import java.util.Iterator;

/**
 * 基于数组实现栈结构
 * 数组的索引为 0 到 x，索引 0 表示栈底，索引 x 表示栈顶。
 * 这样做的原因是因为栈的操作都是栈顶操作，栈底是不动的。数组的右侧操作比左侧更加方便
 *
 * @author zjj_admin
 */
public class ArrayStack<E> implements Stack<E>, Iterable<E> {


    /**
     * 数据数组
     */
    private E[] array;

    /**
     * 栈顶元素的索引，同时也可以表示栈中的元素个数
     */
    private int top;

    /**
     * 栈的容量
     */
    private int capacity;

    @SuppressWarnings("all")
    public ArrayStack(int capacity) {
        if (capacity < 0) {
            throw new IndexOutOfBoundsException("capacity 必须大于 0......");
        }
        this.capacity = capacity;
        top = -1;
        array = (E[]) new Object[capacity];
    }

    @Override
    public boolean push(E value) {
        if (isFull()) {
            return false;
        }
        top++;
        array[top] = value;
        return true;
    }

    @Override
    public E pop() {
        if (isEmpty()) {
            return null;
        }
        E first = array[top];
        top--;
        return first;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return array[top];
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public boolean isFull() {
        return top == capacity - 1;
    }

    @Override
    public int size() {
        return top + 1;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            //遍历时，从栈顶开始遍历
            int index = top;

            @Override
            public boolean hasNext() {
                return index >= 0;
            }

            @Override
            public E next() {
                E value = array[index];
                index--;
                return value;
            }
        };
    }

    /**
     * 重写方法
     * 将栈中的元素从栈顶到栈底依次打印
     *
     * @return
     */
    @SuppressWarnings("all")
    @Override
    public String toString() {
        E[] a = (E[]) new Object[top + 1];
        int j = top;
        for (int i = top; i >= 0; i--) {
            a[j - i] = array[i];
        }
        return Arrays.toString(a);
    }
}
